package ua.org.extjsbuilder.parser.runtime.builder;

import java.io.IOException;
import java.io.Writer;
import java.util.LinkedList;
import java.util.List;

import ua.org.extjsbuilder.parser.IInstruction;
import ua.org.extjsbuilder.parser.IRuntime;
import ua.org.extjsbuilder.parser.IRuntimeBuilder;
import ua.org.extjsbuilder.parser.IScope;
import ua.org.extjsbuilder.parser.IToken;
import ua.org.extjsbuilder.parser.JSErrorHandler;
import ua.org.extjsbuilder.parser.JSObject;
import ua.org.extjsbuilder.parser.runtime.AbstractToken;
import ua.org.extjsbuilder.parser.runtime.UnparsedToken;
import ua.org.extjsbuilder.parser.runtime.data.JSConstants;

public abstract class AbstractRuntimeBuilder extends AbstractToken
		implements IRuntimeBuilder, IRuntime {
	private List<IInstruction> instructions;
	private String name;
	
	public AbstractRuntimeBuilder(IToken token) {
		super(new char[0],token==null?-1:token.getLine());
	}
	
	protected AbstractRuntimeBuilder(int line) {
		super(new char[0],line);
	}

	public IRuntime createRuntime(String name, JSErrorHandler handler) {
		if(instructions!=null){
			return this;
		}
		this.name = name;
		instructions = new LinkedList<IInstruction>();
		GlobalInterpreter state = new GlobalInterpreter(getStartToken());
		state.setHandler(handler);
		while(state.next()){
			if(state.isComplete()){
				instructions.add(state.getLastComplete());
			}
		}
		
		return this;
	}

	public String getName() {
		return name;
	}

	protected abstract UnparsedToken getStartToken();
	
	public void compile(Writer out, boolean optimize) throws IOException {
		for(IInstruction instruction : instructions){
			instruction.compile(out, optimize);
		}
	}

	public JSObject execute(IScope scope, JSObject[] args) {
		for(IInstruction instruction : instructions){
			instruction.execute(scope, args);
		}
		return JSConstants.UNDEFINED;
	}
}
